#include <rtthread.h>
#include "drivers/usb_device.h"

int dcd_set_address(udcd_t dcd, rt_uint8_t address)
{
    RT_ASSERT(dcd != RT_NULL);
    RT_ASSERT(dcd->ops != RT_NULL);
    RT_ASSERT(dcd->ops->set_address != RT_NULL);

    return dcd->ops->set_address(dcd, address);
}

int dcd_ep_enable(udcd_t dcd, uep_t ep)
{
    RT_ASSERT(dcd != RT_NULL);
    RT_ASSERT(dcd->ops != RT_NULL);
    RT_ASSERT(dcd->ops->ep_setenable != RT_NULL);

    return dcd->ops->ep_setenable(dcd, ep, 1);
}

int dcd_ep_disable(udcd_t dcd, uep_t ep)
{
    RT_ASSERT(dcd != RT_NULL);
    RT_ASSERT(dcd->ops != RT_NULL);
    RT_ASSERT(dcd->ops->ep_setenable != RT_NULL);

    return dcd->ops->ep_setenable(dcd, ep, 0);
}

int dcd_ep_read(udcd_t dcd, rt_uint8_t address, void *buffer, size_t size)
{
    int ret;

    RT_ASSERT(dcd != RT_NULL);
    RT_ASSERT(dcd->ops != RT_NULL);
    RT_ASSERT(dcd->ops->ep_xmit != RT_NULL);

    ret = dcd->ops->ep_xmit(dcd, address, buffer, size, 0);

    return ret;
}

int dcd_ep_write(udcd_t dcd, rt_uint8_t address, void *buffer, rt_size_t size)
{
    int ret;

    RT_ASSERT(dcd != RT_NULL);
    RT_ASSERT(dcd->ops != RT_NULL);
    RT_ASSERT(dcd->ops->ep_xmit != RT_NULL);

    ret = dcd->ops->ep_xmit(dcd, address, buffer, size, 1);

    return ret;
}

int dcd_ep_set_stall(udcd_t dcd, rt_uint8_t address)
{    
    RT_ASSERT(dcd != RT_NULL);
    RT_ASSERT(dcd->ops != RT_NULL);
    RT_ASSERT(dcd->ops->ep_setstall != RT_NULL);

    return dcd->ops->ep_setstall(dcd, address, 1);
}

int dcd_ep_clear_stall(udcd_t dcd, rt_uint8_t address)
{
    RT_ASSERT(dcd != RT_NULL);
    RT_ASSERT(dcd->ops != RT_NULL);
    RT_ASSERT(dcd->ops->ep_setstall != RT_NULL);

    return dcd->ops->ep_setstall(dcd, address, 0);
}

int rt_udc_start(udcd_t dcd)
{
    return dcd->ops->dc_setenable(dcd, 1);
}

int rt_udc_stop(udcd_t dcd)
{
    return dcd->ops->dc_setenable(dcd, 0);
}

int dcd_ep0_send_status(udcd_t dcd)
{
    RT_ASSERT(dcd != RT_NULL);
    RT_ASSERT(dcd->ops != RT_NULL);
    RT_ASSERT(dcd->ops->ep0_send_status != RT_NULL);

    return dcd->ops->ep0_send_status();
}
